home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / keyb / visitype.zip / VISITYPE.ASM < prev    next >
Assembly Source File  |  1986-10-11  |  10KB  |  436 lines

  1. vectors segment at 0H        ; set up segment to intercept Interrupts
  2.  
  3.     org    9H*4        ; the keyboard Interrupt
  4. keyboard_int    label    word
  5.  
  6.     org    1CH*4        ; timer interrupt
  7. timer_vector    label    word
  8.  
  9. vectors ends
  10.  
  11.  
  12. screen    segment at 0B000H    ; a dummy segment to use as the
  13. screen    ends            ; extra segment
  14.  
  15.  
  16. rom_bios_data    segment at 40H    ; bios statuses held here, also keyboard buffer
  17.  
  18.     org    1AH
  19. head    dw    ?        ; unread chars go from head to tail
  20. tail    dw    ?
  21. buffer    dw    16 dup (?)    ; the buffer itself
  22.  
  23. buffer_end    label    word
  24.  
  25. rom_bios_data    ends
  26.  
  27.  
  28. code_seg     segment
  29.  
  30.     assume    cs:code_seg
  31.  
  32.     org    100H        ; org = 100H to make this into a .COM file
  33.  
  34. first:    jmp    load_buffer    ; first time through
  35.  
  36. copy_right        db    'Copyright 1986 Ziff-Davis Publishing Co.'
  37. buff            dw    0
  38. buff2            dw    159 dup(0)
  39. pad_offset        dw    0        ; chooses 1st 160 bytes or 2nd
  40. screen_seg_offset    dw    0        ; 0 for mono, 8000H for graphics
  41. io_char            dw    1        ; holds addr of put or get_char
  42. old_head         dw    1        ; to check for typeahead
  43. display_on        db    0        ; 0 -> off
  44. status_port        dw    0        ; video controller status port
  45. near_attrib_flag     db    0        ; used in put_char
  46.  
  47. old_keyboard_int_label    label    dword
  48. old_keyboard_int     dw    0    ; location of old kbd interrupt
  49.             dw    0
  50.  
  51. rom_timer_label        label    dword
  52. rom_timer        dw    0    ; the timer interrupt's address
  53.             dw    0
  54.  
  55.  
  56. bufstuff proc    near        ; the keyboard interrupt will now come here
  57.  
  58.     assume    cs:code_seg
  59.  
  60.     push    ax        ; save the used registers for good form
  61.     push    bx
  62.     push    cx
  63.     push    dx
  64.     push    di
  65.     push    si
  66.     push    ds
  67.     push    es
  68.     pushf                ; first, call old keyboard interrupt
  69.     call    old_keyboard_int_label
  70.  
  71.     assume    ds:rom_bios_data     ; examine the char just put in
  72.  
  73.     mov    bx,rom_bios_data
  74.     mov    ds,bx
  75.     mov    bx,tail            ; point to current tail
  76.     cmp    bx,head            ; if at head, kbd int has deleted char
  77.     jne    cont
  78.  
  79.     jmp    out            ; so leave
  80.  
  81. cont:
  82.     mov    dx,tail            ; read a char - head advances
  83.     sub    dx,2            ; point to just read in character
  84.     cmp    dx,offset buffer     ; did we undershoot buffer?
  85.     jae    nowrap            ; nope
  86.  
  87.     mov    dx,offset buffer_end    ; yes - move to buffer top
  88.     sub    dx,2        
  89.  
  90. nowrap:
  91.     mov    bx,dx
  92.     mov    cx,[bx]            ; get key in cx
  93.     cmp    cx,buff            ; is it where we were before?
  94.     jne    t10
  95.  
  96.     mov    bx,head            ; has the head moved?
  97.     cmp    bx,old_head
  98.     je    t11            ; if yes, we have moved
  99.  
  100. t10:
  101.     cmp    buff2,0
  102.     jne    remove            ; if there's something in buff2,
  103.  
  104. t11:
  105.     cmp    dx,head            ; remove char in kbd buffer
  106.     jne    remove
  107.  
  108.     jmp    out            ; do nothing this pass
  109.  
  110. ; more than one char in buffer - remove one
  111.  
  112. remove:
  113.     mov    bx,dx
  114.     mov    tail,dx            ; remove character by adjusting tail
  115.     mov    dx,[bx]            ; store character in buffer
  116.     mov    cx,80
  117.     mov    bx,0            ; find end of visitype buffer
  118.  
  119. check:
  120.     cmp    buff2[bx],0
  121.     je    bufend
  122.  
  123.     add    bx,2
  124.     loop    check
  125.  
  126.     cmp    dx,0E08H         ; was this key a rubout?
  127.     jne    out            ; no, and buffer filled - leave
  128.  
  129.     mov    bx,158            ; yes, buff full but rubout last char
  130.     mov    word ptr buff[bx],0
  131.     mov    bx,head
  132.     mov    old_head,bx        ; store this for next time
  133.     mov    dx,[bx]            ; always load buff
  134.     mov    buff,dx
  135.     jmp    out            ; can't hold more than 80
  136.  
  137. bufend:
  138.     cmp    dx,0E08H         ; rubout (and buffer not full)?
  139.     jne    nodel            ; no, don't del
  140.  
  141. del:
  142.     sub    bx,2            ; yes, delete last key
  143.     cmp    bx,0FFFEH        ; gone too far?
  144.     jl    out
  145.  
  146.     jne    paddel
  147.  
  148.     mov    cx,tail            ; del the one char in kdb buffer
  149.     mov    head,cx            ; by making tail = head
  150.     mov    buff,0
  151.     jmp    short chkdis
  152.  
  153. paddel:
  154.     mov    dx,0            ; dx -> 0 if we are deleting
  155.  
  156. nodel:
  157.     mov    buff2[bx],dx        ; load key in visitype buffer
  158.     mov    bx,head
  159.     mov    old_head,bx        ; and store the old head to check later
  160.     mov    dx,[bx]            ; always reload buff
  161.     mov    buff,dx
  162.  
  163. chkdis:
  164.     cmp    display_on,0        ; are we on?
  165.     jne    flash            ; yes, call display
  166.  
  167.     mov    display_on,0FFH        ; store what's on the screen first
  168.     mov    pad_offset,160    
  169.     lea    ax,get_char        ; make io use get-char so it does
  170.     mov    io_char,ax    
  171.     call    io            ; get top line from screen
  172.  
  173. flash:
  174.     call    display            ; display visitype's top line
  175.  
  176. out:
  177.     pop    es            ; having done pushes, here are the pops
  178.     pop    ds
  179.     pop    si
  180.     pop    di
  181.     pop    dx
  182.     pop    cx
  183.     pop    bx
  184.     pop    ax
  185.     iret                ; an interrupt needs an iret
  186.  
  187. bufstuff endp
  188.  
  189.  
  190. display proc    near            ; puts the whole pad on the screen
  191.  
  192.     push    ax
  193.     mov    near_attrib_flag,0
  194.     mov    pad_offset,0        ; use 1st bytes of pad memory
  195.     lea    ax,put_char        ; make io use put-char so it does
  196.     mov    io_char,ax    
  197.     call    io            ; put result on screen
  198.     pop    ax
  199.     ret                ; leave
  200.  
  201. display endp
  202.  
  203.  
  204. get_char     proc    near    ; gets a char from screen and advances position
  205.  
  206.     assume    es:screen,ds:rom_bios_data
  207.  
  208.     push    dx
  209.     mov    si,2        ; loop twice, once for char, once for attribute
  210.     mov    dx,status_port    ; get ready to read video controller status
  211.  
  212. g_wait_low:            ; start waiting for a new horizontal scan -
  213.     in    al,dx        ; make sure the video controller scan status
  214.     test    al,1        ; is low
  215.     jnz    g_wait_low
  216.  
  217. g_wait_high:            ; after port has gone low, it must go high
  218.     in    al,dx        ; before it is safe to read directly from
  219.     test    al,1        ; the screen buffer in memory
  220.     jz    g_wait_high
  221.  
  222.     mov    ax,es:[di]    ; do the move from the screen, one byte at a time
  223.     inc    di        ; move to next screen location        
  224.     dec    si        ; decrement loop counter
  225.     cmp    si,0        ; are we done?
  226.     je    leave        ; yes
  227.  
  228.     mov    buff[bx],ax    ; no - put char we got into buff
  229.     jmp    g_wait_low    ; do it again
  230.  
  231. leave:
  232.     add    bx,2
  233.     pop    dx
  234.     ret
  235.  
  236. get_char     endp
  237.  
  238.  
  239. put_char     proc    near    ; puts one char on screen and advances position
  240.  
  241.     push    dx
  242.     cli
  243.     mov    ah,byte ptr buff[bx]    
  244.     mov    si,2        ; loop twice, once for char, once for attribute
  245.     mov    dx,status_port    ; get ready to read video controller status
  246.  
  247. p_wait_low:            ; start waiting for a new horizontal scan -
  248.     in    al,dx        ; make sure the video controller scan status
  249.     test    al,1        ; is low
  250.     jnz    p_wait_low
  251.  
  252. p_wait_high:            ; after port has gone low, it must go high
  253.     in    al,dx        ; before it is safe to write directly to
  254.     test    al,1        ; the screen buffer in memory
  255.     jz    p_wait_high
  256.  
  257.     mov    es:[di],ah    ; move to screen, one byte at a time
  258.     mov    ah,byte ptr buff[bx+1]
  259.     cmp    near_attrib_flag,0
  260.     jne    incdi
  261.  
  262.     mov    ah,byte ptr buff[bx+161]
  263.  
  264. incdi:
  265.     inc    di        ; point to next screen postion
  266.     dec    si        ; decrement loop counter
  267.     jnz    p_wait_low    ; if not zero, do it one more time
  268.  
  269.     add    bx,2
  270.     pop    dx
  271.     sti
  272.     ret            ; exeunt
  273.  
  274. put_char     endp
  275.  
  276.  
  277. io    proc    near        ; this scans over screen positions on top line
  278.  
  279.     assume    es:screen    ; use screen as extra segment
  280.  
  281.     mov    bx,screen
  282.     mov    es,bx
  283.     mov    di,screen_seg_offset    ; di will be pointer to screen postion
  284.     mov    bx,pad_offset        ; bx will be location pointer
  285.     mov    cx,80
  286.  
  287. char_loop:
  288.     call    io_char            ; call put-char or get-char
  289.     loop    char_loop        ; if not zero, scan over next character
  290.     ret                ; finished
  291.  
  292. io    endp
  293.  
  294.  
  295.     assume    ds:code_seg
  296.  
  297. intercept_timer     proc     near        ; this completes filling the buffer
  298.  
  299. ; if no keys in buffer, put next one in
  300.  
  301.     push    ds            ; save DS since we'll change it
  302.     push    cs            ; put current value of CS into DS
  303.     pop    ds
  304.     pushf
  305.     call    rom_timer_label        ; make obligatory call
  306.     cmp    buff2,0
  307.     jne    go            ; no, leave
  308.  
  309.     jmp    out1
  310.  
  311. go:
  312.     cli                ; yes, start by clearing interrupts
  313.     push    es
  314.     push    ds            ; save these
  315.     push    si
  316.     push    di
  317.     push    dx
  318.     push    cx
  319.     push    bx
  320.     push    ax
  321.  
  322.     assume    ds:rom_bios_data     ; point to the keyboard buffer again
  323.  
  324.     mov    ax,rom_bios_data
  325.     mov    ds,ax
  326.     mov    bx,tail            ; prepare to put characters in at tail
  327.     cmp    head,bx            ; if kbd buff not empty, leave
  328.     jne    finstuff
  329.  
  330. stuff:
  331.     mov    ax,word ptr buff2    ; get the char to put in kbd buffer
  332.     mov    cx,79            ; now slide the rest over
  333.     mov    bx,0
  334.  
  335. slide:
  336.     mov    dx,buff[bx+2]        ; do this word by word
  337.     mov    buff[bx],dx
  338.     add    bx,2
  339.     inc    si
  340.     loop    slide            ; slides slides buff to the left
  341.     mov    word ptr buff2[bx-2],0
  342.     mov    dx,head            ; store this to check if user is typing
  343.     mov    old_head,dx        ; while we drain buff
  344.     mov    dx,tail            ; find position in buffer from bx
  345.     add    dx,2            ; move to next position for this word
  346.     cmp    dx,offset buffer_end    ; are we past the end?
  347.     jl    no_wrap            ; no, don't wrap
  348.  
  349.     mov    dx,offset buffer     ; do the wrap rap
  350.  
  351. no_wrap:
  352.     cmp    dx,head            ; buffer full but not yet done?
  353.     je    finstuff         ; time to leave, come back later
  354.  
  355.     mov    bx,tail            ; prepare to put characters in at tail
  356.     mov    [bx],ax            ; put into buffer
  357.     mov